﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Tetris
{
    [Serializable]
    public class Game
    {
        //atributes
        private int minute;
        private int second;
        private int score;
        private int nbRows;
        private int consecutiveRows;
        private int level;
        private String pseudo;
        private Cell[][] plateau;
        private Shape nextShape;
        private Shape curShape;
        public const int NBROW=29;
        public const int NBCOLUMN=11;
        public delegate void UpdateMultiGame(Game game);
        public bool isInMultigame;

        /// <summary>
        /// default constructor
        /// </summary>
        public Game()
        {
            score = 0;
            level = 1;
            nbRows = 0;
            minute = 0;
            second = 0;
            pseudo = "user";
            consecutiveRows = 0;
            isInMultigame = false;

            //initialization of the plateau (array of Cell)
            plateau = new Cell[NBCOLUMN][];
            for (int i = 0; i < NBCOLUMN; i++)
            {
                plateau[i] = new Cell[NBROW];
            }
            for (int i = 0; i < NBCOLUMN; i++)
            {
                for (int j = 0; j < NBROW; j++)
                {
                    plateau[i][j]= new Cell();
                }
            }

           // set the edge of the game
           for (int i = 0; i < NBCOLUMN; i++)
            {
                plateau[i][NBROW-1].Available=false;
            }
            for (int j = 0; j < NBROW; j++)
            {
                plateau[0][j].Available=false;
                plateau[NBCOLUMN-1][j].Available=false;
            }

            //initalize the current and the next shape randomly
            curShape = randomShape();
            nextShape = randomShape();           

        }

        
        /// <summary>
        /// constructor wich define the name of the player
        /// </summary>
        /// <param name="user">name of the player</param>
        public Game(String user)
        {
            score = 0;
            level = 1;
            nbRows = 0;
            minute = 0;
            second = 0;
            pseudo=user;

            //initialization of the plateau (array of Cell)
            plateau = new Cell[NBCOLUMN][];
            for (int i = 0; i < NBCOLUMN; i++)
            {
                plateau[i] = new Cell[NBROW];
            }
            for (int i = 0; i < NBCOLUMN; i++)
            {
                for (int j = 0; j < NBROW; j++)
                {
                    plateau[i][j] = new Cell();
                }
            }

            // set the edge of the game
            for (int i = 0; i < NBCOLUMN; i++)
            {
                plateau[i][NBROW - 1].Available=false;
            }
            for (int j = 0; j < NBROW; j++)
            {
                plateau[0][j].Available=false;
                plateau[NBCOLUMN - 1][j].Available=false;
            }

            //initalize the current and the next shape randomly
            curShape = randomShape();
            nextShape = randomShape();
        }

        /// <summary>
        /// returns a random Shape between all the known shapes (Square, line, arrow...)
        /// </summary>
        /// <returns>The random shape</returns>
        public Shape randomShape()
        {
            Random random = new Random();
            Shape s=null;
            switch (random.Next(7))
            {
                case 0:
                    s = new Square(true);
                    break;
                case 1:
                    s = new Line(true);
                    break;
                case 2:
                    s = new RightL(true);
                    break;
                case 3:
                    s = new Arrow(true);
                    break;
                case 4:
                    s = new LeftL(true);
                    break;
                case 5:
                    s = new LeftS(true);
                    break;
                case 6:
                    s = new RightS(true);
                    break;
            }
            return s;
        }
        
        /// <summary>
        /// check the plateau if the game is ended
        /// </summary>
        /// <returns>returns true if the game is ended , else returns false</returns>
        public Boolean isEnd()
        {    
          for (int i = 1; i <NBCOLUMN-1; i++)
          {
                if (plateau[i][2].Available==false)
                {
                   return true;
                }
           }
           return false;
        }
        
        /// <summary>
        /// check if any rows are complete
        /// </summary>
        /// <returns>returns the number of the row to delete or 0 if not any rows to delete</returns>
        public int checkRow()
        {
            int cpt = 0;
            for (int i = NBROW-2; i > 0; i--)
            {
                for (int j = 1; j < NBCOLUMN-1; j++)
                {
                    if (plateau[j][i].Available == false)
                    {
                        cpt++;
                    }
                    if (cpt == 9)
                    {
                        return i;
                    }
                }
                cpt = 0;
            }
            return 0;
        }
        /// <summary>
        /// delete the row wich is targeted in argument and scroll down the part of the plateau on top of it
        /// </summary>
        /// <param name="row">the row which needs to be delete</param>
        public void deleteRow(int row)
        {
            for (int i = row; i > 1; i--)
            {
                for(int j=1;j<10;j++)
                {
                    plateau[j][i].Available=plateau[j][i - 1].Available;
                }
            }
        }

        /// <summary>
        /// add a row of concrete to the targeted player ( mode multi only)
        /// </summary>
        public void addRow()
        {
            // To do
        }

        /// <summary>
        /// Return the game Plateau
        /// </summary>
        public Cell[][] Plateau
        {
            get
            {
                return plateau;
            }
            set
            {
                plateau = value;
            }

        }

        /// <summary>
        /// Get/Set current Shape
        /// </summary>
        public Shape CurShape
        {
            get
            {
                return curShape;
            }
            set
            {
                curShape = value;
            }
        }

        /// <summary>
        /// Get/Set next shape
        /// </summary>
        public Shape NextShape
        {
            get
            {
                return nextShape;
            }
            set
            {
                this.nextShape = value;
            }
        }

        /// <summary>
        /// Get/set score
        /// </summary>
        public int Score
        {
            get
            {
                return score;
            }
            set
            {
                this.score = value;
            }
        }

        /// <summary>
        /// Get/set level
        /// </summary>
        public int Level
        {
            get 
            { 
                return level; 
            }
            set 
            { 
                level = value; 
            }
        }

        /// <summary>
        /// get set Minute
        /// </summary>
        public int Minute
        {
            get
            {
                return minute;
            }
            set
            {
                minute = value;
            }
        }

        /// <summary>
        /// get/set second
        /// </summary>
        public int Second
        {
            get
            {
                return second;
            }
            set
            {
                second = value;
            }
        }

        /// <summary>
        /// get/set nbrows
        /// </summary>
        public int NbRows
        {
            get
            {
                return nbRows;
            }
            set
            {
                nbRows = value;
            }
        }

        /// <summary>
        /// get/set consecutivesRows
        /// </summary>
        public int ConsecutiveRows
        {
            get 
            { 
                return consecutiveRows; 
            }
            set 
            { 
                consecutiveRows = value; 
            }
        }

        /// <summary>
        /// get/set pseudo
        /// </summary>
        public String Pseudo
        {
            get
            {
                return pseudo;
            }
            set
            {
                pseudo = value;
            }
        }

        /// <summary>
        /// Check and change the level of the game
        /// </summary>
        public void changeLevel()
        {
            // to do
        }

        /// <summary>
        /// Choose a random Shape for the nextShape
        /// </summary>
        public void followingShape()
        {
            nextShape = randomShape();
        }

        /// <summary>
        /// Deal with the game duration
        /// </summary>
        public void setClock()
        {
            if (second < 60)
            {
                second++;
            }
            else
            {
                minute++;
                second = 0;
            }
        }

        /// <summary>
        /// return a duration formated like 'min:sec'
        /// </summary>
        /// <returns></returns>
        public string printClock()
        {
            if(second<10)
                return minute.ToString() + ":" + "0"+second.ToString();
            else
                return minute.ToString() + ":" + second.ToString();
        }
    }
}
